﻿// <file>
//     <copyright see="prj:///doc/copyright.txt"/>
//     <license see="prj:///doc/license.txt"/>
//     <owner name="Oliver Rau" email="mail@olira.de"/>
//     <version>$Revision: 9 $</version>
//     <created>12.08.2006 19:11</created>
// </file>

using System;
using System.Collections.Generic;
using System.IO;
using ICSharpCode.Core;

namespace ns2kml
{
	/// <summary>
	/// Description of NS1Factory.
	/// </summary>
	public class NS1FileHelper
	{
		public static List<APInfo> GetInfoFromFile(string fileName)
		{
			LoggingService.DebugFormatted("NS1FileHelper started: {0}", fileName);
			
			Stream stream = File.OpenRead(fileName);
			BinaryReader reader = new BinaryReader(stream);
			
			// first let's check the signature
			string dwSignature = new string(reader.ReadChars(4));
			uint   dwFileVer   = reader.ReadUInt32();
			uint   apCount    = reader.ReadUInt32();
			
			LoggingService.DebugFormatted("Signature: {0} FileVersion: {1} ApCount: {2}", 
			                              dwSignature, dwFileVer, apCount);
			
			if (dwSignature != "NetS" || dwFileVer != 12) {
				stream.Close();
				reader.Close();
				throw new NotSupportedException("Sorry, but only NS1 files with a version of 12 are currently supported!");
			}
			
			List<APInfo> apInfo = new List<APInfo>((int)apCount);
			
			for (int i=0; i < apCount; i++) {
				apInfo.Add(GetAPInfoFromReader(reader));
			}
			
			stream.Close();
			reader.Close();
			
			return apInfo;
		}
		
		static APInfo GetAPInfoFromReader(BinaryReader br)
		{
			APInfo info = new APInfo();
			
			string temp;
			
			byte ssidLength = br.ReadByte();
			info.SSID = new string(br.ReadChars(ssidLength));
			
			byte[] bssid = br.ReadBytes(6);
			for (int i=0; i < 6; i++) {
				temp = Convert.ToString(bssid[i], 16);
				if (temp.Length == 1)
					temp = "0" + temp;
				info.BSSID += (i==0?temp:":" + temp);
			}
			
			info.MaxSignal = br.ReadInt32();
			info.MinNoise  = br.ReadInt32();
			info.MaxSNR    = br.ReadInt32();
			info.Flags     = (WifiFlag)br.ReadUInt32();
			info.BeaconInterval = br.ReadUInt32();
			info.FirstSeen = DateTime.FromFileTimeUtc(br.ReadInt64());
			info.LastSeen  = DateTime.FromFileTimeUtc(br.ReadInt64());
			
			info.BestPosition.Latitude  = br.ReadDouble();
			info.BestPosition.Longitude = br.ReadDouble();
			
			uint dataCount = br.ReadUInt32();
			
			info.APData = new List<APData>((int)dataCount);
			
			for (int i = 0; i<dataCount; i++) {
				info.APData.Add(GetAPDataFromReader(br));
			}
			
			byte nameLength = br.ReadByte();
			info.Name = new string(br.ReadChars(nameLength));
			
			info.Channels = br.ReadUInt64();
			info.LastChannel = br.ReadUInt32();
			
			uint ipAddress = br.ReadUInt32();
			// TODO: IPAddress
			info.MinSignal = br.ReadInt32();
			info.MaxNoise  = br.ReadInt32();
			info.DataRate  = br.ReadUInt32();
			
			// TODO: IP Subnet, IP Mask
			uint ipSubnet = br.ReadUInt32();
			uint ipMask   = br.ReadUInt32();
			
			info.ApFlags = br.ReadUInt32();
			
			uint ieLength = br.ReadUInt32();
			info.InformationElements = br.ReadBytes((int)ieLength);
			
			LoggingService.DebugFormatted("BSSID: {0}", info.BSSID);
			LoggingService.DebugFormatted("LastSeen:  {0}", info.LastSeen.ToLocalTime());
			LoggingService.Debug("----");
			return info;
		}
		
		static APData GetAPDataFromReader(BinaryReader br)
		{
			APData data = new APData();
			
			int expectedLength = 20;
			int currentPos = 0;
			
			try {
			
			data.Time   = DateTime.FromFileTimeUtc(br.ReadInt64());
			currentPos += 8;
			data.Signal = br.ReadInt32();
			currentPos += 4;
			data.Noise  = br.ReadInt32();
			currentPos += 4;
			data.LocationSource = br.ReadInt32();
			currentPos += 4;
			
			if (data.LocationSource == 1)
				data.GPSData = GetGPSDataFromReader(br);
			} catch (Exception ex) {
				if (currentPos < expectedLength) {
					br.ReadBytes(expectedLength - currentPos);
				}
				return null;
			}
			
			return data;
		}
		
		static GPSData GetGPSDataFromReader(BinaryReader br)
		{
			GPSData gpsData   = new GPSData();
			
			gpsData.Position.Latitude  = br.ReadDouble();
			gpsData.Position.Longitude = br.ReadDouble();
			gpsData.Position.Altitude  = br.ReadDouble();
			
			gpsData.NumSats   = br.ReadUInt32();
			gpsData.Speed     = br.ReadDouble();
			gpsData.Track     = br.ReadDouble();
			gpsData.MagVariation = br.ReadDouble();
			gpsData.Hdop      = br.ReadDouble();
			
			return gpsData;
		}
	}
}
